package io.github.sds100.keymapper.system.inputevents

import android.view.KeyEvent
import io.github.sds100.keymapper.common.utils.withFlag

object KeyEventUtils {
    private val KEYCODES: IntArray = intArrayOf(
        KeyEvent.KEYCODE_SOFT_LEFT,
        KeyEvent.KEYCODE_SOFT_RIGHT,
        KeyEvent.KEYCODE_HOME,
        KeyEvent.KEYCODE_BACK,
        KeyEvent.KEYCODE_CALL,
        KeyEvent.KEYCODE_ENDCALL,
        KeyEvent.KEYCODE_0,
        KeyEvent.KEYCODE_1,
        KeyEvent.KEYCODE_2,
        KeyEvent.KEYCODE_3,
        KeyEvent.KEYCODE_4,
        KeyEvent.KEYCODE_5,
        KeyEvent.KEYCODE_6,
        KeyEvent.KEYCODE_7,
        KeyEvent.KEYCODE_8,
        KeyEvent.KEYCODE_9,
        KeyEvent.KEYCODE_STAR,
        KeyEvent.KEYCODE_POUND,
        KeyEvent.KEYCODE_DPAD_UP,
        KeyEvent.KEYCODE_DPAD_DOWN,
        KeyEvent.KEYCODE_DPAD_LEFT,
        KeyEvent.KEYCODE_DPAD_RIGHT,
        KeyEvent.KEYCODE_DPAD_CENTER,
        KeyEvent.KEYCODE_VOLUME_UP,
        KeyEvent.KEYCODE_VOLUME_DOWN,
        KeyEvent.KEYCODE_POWER,
        KeyEvent.KEYCODE_CAMERA,
        KeyEvent.KEYCODE_CLEAR,
        KeyEvent.KEYCODE_A,
        KeyEvent.KEYCODE_B,
        KeyEvent.KEYCODE_C,
        KeyEvent.KEYCODE_D,
        KeyEvent.KEYCODE_E,
        KeyEvent.KEYCODE_F,
        KeyEvent.KEYCODE_G,
        KeyEvent.KEYCODE_H,
        KeyEvent.KEYCODE_I,
        KeyEvent.KEYCODE_J,
        KeyEvent.KEYCODE_K,
        KeyEvent.KEYCODE_L,
        KeyEvent.KEYCODE_M,
        KeyEvent.KEYCODE_N,
        KeyEvent.KEYCODE_O,
        KeyEvent.KEYCODE_P,
        KeyEvent.KEYCODE_Q,
        KeyEvent.KEYCODE_R,
        KeyEvent.KEYCODE_S,
        KeyEvent.KEYCODE_T,
        KeyEvent.KEYCODE_U,
        KeyEvent.KEYCODE_V,
        KeyEvent.KEYCODE_W,
        KeyEvent.KEYCODE_X,
        KeyEvent.KEYCODE_Y,
        KeyEvent.KEYCODE_Z,
        KeyEvent.KEYCODE_COMMA,
        KeyEvent.KEYCODE_PERIOD,
        KeyEvent.KEYCODE_ALT_LEFT,
        KeyEvent.KEYCODE_ALT_RIGHT,
        KeyEvent.KEYCODE_SHIFT_LEFT,
        KeyEvent.KEYCODE_SHIFT_RIGHT,
        KeyEvent.KEYCODE_TAB,
        KeyEvent.KEYCODE_SPACE,
        KeyEvent.KEYCODE_SYM,
        KeyEvent.KEYCODE_EXPLORER,
        KeyEvent.KEYCODE_ENVELOPE,
        KeyEvent.KEYCODE_ENTER,
        KeyEvent.KEYCODE_FORWARD_DEL,
        KeyEvent.KEYCODE_DEL,
        KeyEvent.KEYCODE_GRAVE,
        KeyEvent.KEYCODE_MINUS,
        KeyEvent.KEYCODE_EQUALS,
        KeyEvent.KEYCODE_LEFT_BRACKET,
        KeyEvent.KEYCODE_RIGHT_BRACKET,
        KeyEvent.KEYCODE_BACKSLASH,
        KeyEvent.KEYCODE_SEMICOLON,
        KeyEvent.KEYCODE_APOSTROPHE,
        KeyEvent.KEYCODE_SLASH,
        KeyEvent.KEYCODE_AT,
        KeyEvent.KEYCODE_HEADSETHOOK,
        KeyEvent.KEYCODE_FOCUS,
        KeyEvent.KEYCODE_PLUS,
        KeyEvent.KEYCODE_MENU,
        KeyEvent.KEYCODE_NOTIFICATION,
        KeyEvent.KEYCODE_SEARCH,
        KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE,
        KeyEvent.KEYCODE_MEDIA_STOP,
        KeyEvent.KEYCODE_MEDIA_NEXT,
        KeyEvent.KEYCODE_MEDIA_PREVIOUS,
        KeyEvent.KEYCODE_MEDIA_REWIND,
        KeyEvent.KEYCODE_MEDIA_FAST_FORWARD,
        KeyEvent.KEYCODE_PAGE_UP,
        KeyEvent.KEYCODE_PAGE_DOWN,
        KeyEvent.KEYCODE_PICTSYMBOLS,
        KeyEvent.KEYCODE_SWITCH_CHARSET,
        KeyEvent.KEYCODE_BUTTON_A,
        KeyEvent.KEYCODE_BUTTON_B,
        KeyEvent.KEYCODE_BUTTON_C,
        KeyEvent.KEYCODE_BUTTON_X,
        KeyEvent.KEYCODE_BUTTON_Y,
        KeyEvent.KEYCODE_BUTTON_Z,
        KeyEvent.KEYCODE_BUTTON_L1,
        KeyEvent.KEYCODE_BUTTON_R1,
        KeyEvent.KEYCODE_BUTTON_L2,
        KeyEvent.KEYCODE_BUTTON_R2,
        KeyEvent.KEYCODE_BUTTON_THUMBL,
        KeyEvent.KEYCODE_BUTTON_THUMBR,
        KeyEvent.KEYCODE_BUTTON_START,
        KeyEvent.KEYCODE_BUTTON_SELECT,
        KeyEvent.KEYCODE_BUTTON_MODE,
        KeyEvent.KEYCODE_ESCAPE,
        KeyEvent.KEYCODE_CTRL_LEFT,
        KeyEvent.KEYCODE_CTRL_RIGHT,
        KeyEvent.KEYCODE_CAPS_LOCK,
        KeyEvent.KEYCODE_SCROLL_LOCK,
        KeyEvent.KEYCODE_META_LEFT,
        KeyEvent.KEYCODE_META_RIGHT,
        KeyEvent.KEYCODE_FUNCTION,
        KeyEvent.KEYCODE_SYSRQ,
        KeyEvent.KEYCODE_BREAK,
        KeyEvent.KEYCODE_MOVE_HOME,
        KeyEvent.KEYCODE_MOVE_END,
        KeyEvent.KEYCODE_INSERT,
        KeyEvent.KEYCODE_FORWARD,
        KeyEvent.KEYCODE_MEDIA_PLAY,
        KeyEvent.KEYCODE_MEDIA_PAUSE,
        KeyEvent.KEYCODE_MEDIA_CLOSE,
        KeyEvent.KEYCODE_MEDIA_EJECT,
        KeyEvent.KEYCODE_MEDIA_RECORD,
        KeyEvent.KEYCODE_F1,
        KeyEvent.KEYCODE_F2,
        KeyEvent.KEYCODE_F3,
        KeyEvent.KEYCODE_F4,
        KeyEvent.KEYCODE_F5,
        KeyEvent.KEYCODE_F6,
        KeyEvent.KEYCODE_F7,
        KeyEvent.KEYCODE_F8,
        KeyEvent.KEYCODE_F9,
        KeyEvent.KEYCODE_F10,
        KeyEvent.KEYCODE_F11,
        KeyEvent.KEYCODE_F12,
        KeyEvent.KEYCODE_NUM,
        KeyEvent.KEYCODE_NUM_LOCK,
        KeyEvent.KEYCODE_NUMPAD_0,
        KeyEvent.KEYCODE_NUMPAD_1,
        KeyEvent.KEYCODE_NUMPAD_2,
        KeyEvent.KEYCODE_NUMPAD_3,
        KeyEvent.KEYCODE_NUMPAD_4,
        KeyEvent.KEYCODE_NUMPAD_5,
        KeyEvent.KEYCODE_NUMPAD_6,
        KeyEvent.KEYCODE_NUMPAD_7,
        KeyEvent.KEYCODE_NUMPAD_8,
        KeyEvent.KEYCODE_NUMPAD_9,
        KeyEvent.KEYCODE_NUMPAD_DIVIDE,
        KeyEvent.KEYCODE_NUMPAD_MULTIPLY,
        KeyEvent.KEYCODE_NUMPAD_SUBTRACT,
        KeyEvent.KEYCODE_NUMPAD_ADD,
        KeyEvent.KEYCODE_NUMPAD_DOT,
        KeyEvent.KEYCODE_NUMPAD_COMMA,
        KeyEvent.KEYCODE_NUMPAD_ENTER,
        KeyEvent.KEYCODE_NUMPAD_EQUALS,
        KeyEvent.KEYCODE_NUMPAD_LEFT_PAREN,
        KeyEvent.KEYCODE_NUMPAD_RIGHT_PAREN,
        KeyEvent.KEYCODE_MUTE,
        KeyEvent.KEYCODE_VOLUME_MUTE,
        KeyEvent.KEYCODE_INFO,
        KeyEvent.KEYCODE_CHANNEL_UP,
        KeyEvent.KEYCODE_CHANNEL_DOWN,
        KeyEvent.KEYCODE_ZOOM_IN,
        KeyEvent.KEYCODE_ZOOM_OUT,
        KeyEvent.KEYCODE_TV,
        KeyEvent.KEYCODE_WINDOW,
        KeyEvent.KEYCODE_GUIDE,
        KeyEvent.KEYCODE_DVR,
        KeyEvent.KEYCODE_BOOKMARK,
        KeyEvent.KEYCODE_CAPTIONS,
        KeyEvent.KEYCODE_SETTINGS,
        KeyEvent.KEYCODE_TV_POWER,
        KeyEvent.KEYCODE_TV_INPUT,
        KeyEvent.KEYCODE_STB_POWER,
        KeyEvent.KEYCODE_STB_INPUT,
        KeyEvent.KEYCODE_AVR_POWER,
        KeyEvent.KEYCODE_AVR_INPUT,
        KeyEvent.KEYCODE_PROG_RED,
        KeyEvent.KEYCODE_PROG_GREEN,
        KeyEvent.KEYCODE_PROG_YELLOW,
        KeyEvent.KEYCODE_PROG_BLUE,
        KeyEvent.KEYCODE_APP_SWITCH,
        KeyEvent.KEYCODE_BUTTON_1,
        KeyEvent.KEYCODE_BUTTON_2,
        KeyEvent.KEYCODE_BUTTON_3,
        KeyEvent.KEYCODE_BUTTON_4,
        KeyEvent.KEYCODE_BUTTON_5,
        KeyEvent.KEYCODE_BUTTON_6,
        KeyEvent.KEYCODE_BUTTON_7,
        KeyEvent.KEYCODE_BUTTON_8,
        KeyEvent.KEYCODE_BUTTON_9,
        KeyEvent.KEYCODE_BUTTON_10,
        KeyEvent.KEYCODE_BUTTON_11,
        KeyEvent.KEYCODE_BUTTON_12,
        KeyEvent.KEYCODE_BUTTON_13,
        KeyEvent.KEYCODE_BUTTON_14,
        KeyEvent.KEYCODE_BUTTON_15,
        KeyEvent.KEYCODE_BUTTON_16,
        KeyEvent.KEYCODE_LANGUAGE_SWITCH,
        KeyEvent.KEYCODE_MANNER_MODE,
        KeyEvent.KEYCODE_3D_MODE,
        KeyEvent.KEYCODE_CONTACTS,
        KeyEvent.KEYCODE_CALENDAR,
        KeyEvent.KEYCODE_MUSIC,
        KeyEvent.KEYCODE_CALCULATOR,
        KeyEvent.KEYCODE_ZENKAKU_HANKAKU,
        KeyEvent.KEYCODE_EISU,
        KeyEvent.KEYCODE_MUHENKAN,
        KeyEvent.KEYCODE_HENKAN,
        KeyEvent.KEYCODE_KATAKANA_HIRAGANA,
        KeyEvent.KEYCODE_YEN,
        KeyEvent.KEYCODE_RO,
        KeyEvent.KEYCODE_KANA,
        KeyEvent.KEYCODE_ASSIST,
        KeyEvent.KEYCODE_BRIGHTNESS_DOWN,
        KeyEvent.KEYCODE_BRIGHTNESS_UP,
        KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK,
        KeyEvent.KEYCODE_PAIRING,
        KeyEvent.KEYCODE_MEDIA_TOP_MENU,
        KeyEvent.KEYCODE_11,
        KeyEvent.KEYCODE_12,
        KeyEvent.KEYCODE_LAST_CHANNEL,
        KeyEvent.KEYCODE_TV_DATA_SERVICE,
        KeyEvent.KEYCODE_VOICE_ASSIST,
        KeyEvent.KEYCODE_TV_RADIO_SERVICE,
        KeyEvent.KEYCODE_TV_TELETEXT,
        KeyEvent.KEYCODE_TV_NUMBER_ENTRY,
        KeyEvent.KEYCODE_TV_TERRESTRIAL_ANALOG,
        KeyEvent.KEYCODE_TV_TERRESTRIAL_DIGITAL,
        KeyEvent.KEYCODE_TV_SATELLITE,
        KeyEvent.KEYCODE_TV_SATELLITE_BS,
        KeyEvent.KEYCODE_TV_SATELLITE_CS,
        KeyEvent.KEYCODE_TV_SATELLITE_SERVICE,
        KeyEvent.KEYCODE_TV_NETWORK,
        KeyEvent.KEYCODE_TV_ANTENNA_CABLE,
        KeyEvent.KEYCODE_TV_INPUT_HDMI_1,
        KeyEvent.KEYCODE_TV_INPUT_HDMI_2,
        KeyEvent.KEYCODE_TV_INPUT_HDMI_3,
        KeyEvent.KEYCODE_TV_INPUT_HDMI_4,
        KeyEvent.KEYCODE_TV_INPUT_COMPOSITE_1,
        KeyEvent.KEYCODE_TV_INPUT_COMPOSITE_2,
        KeyEvent.KEYCODE_TV_INPUT_COMPONENT_1,
        KeyEvent.KEYCODE_TV_INPUT_COMPONENT_2,
        KeyEvent.KEYCODE_TV_INPUT_VGA_1,
        KeyEvent.KEYCODE_TV_AUDIO_DESCRIPTION,
        KeyEvent.KEYCODE_TV_AUDIO_DESCRIPTION_MIX_UP,
        KeyEvent.KEYCODE_TV_AUDIO_DESCRIPTION_MIX_DOWN,
        KeyEvent.KEYCODE_TV_ZOOM_MODE,
        KeyEvent.KEYCODE_TV_CONTENTS_MENU,
        KeyEvent.KEYCODE_TV_MEDIA_CONTEXT_MENU,
        KeyEvent.KEYCODE_TV_TIMER_PROGRAMMING,
        KeyEvent.KEYCODE_HELP,
        KeyEvent.KEYCODE_NAVIGATE_PREVIOUS,
        KeyEvent.KEYCODE_NAVIGATE_NEXT,
        KeyEvent.KEYCODE_NAVIGATE_IN,
        KeyEvent.KEYCODE_NAVIGATE_OUT,
        KeyEvent.KEYCODE_MEDIA_SKIP_FORWARD,
        KeyEvent.KEYCODE_MEDIA_SKIP_BACKWARD,
        KeyEvent.KEYCODE_MEDIA_STEP_FORWARD,
        KeyEvent.KEYCODE_MEDIA_STEP_BACKWARD,
        KeyEvent.KEYCODE_STEM_PRIMARY,
        KeyEvent.KEYCODE_STEM_1,
        KeyEvent.KEYCODE_STEM_2,
        KeyEvent.KEYCODE_STEM_3,
        KeyEvent.KEYCODE_DPAD_UP_LEFT,
        KeyEvent.KEYCODE_DPAD_DOWN_LEFT,
        KeyEvent.KEYCODE_DPAD_UP_RIGHT,
        KeyEvent.KEYCODE_DPAD_DOWN_RIGHT,
        KeyEvent.KEYCODE_SOFT_SLEEP,
        KeyEvent.KEYCODE_CUT,
        KeyEvent.KEYCODE_COPY,
        KeyEvent.KEYCODE_PASTE,
        KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP,
        KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN,
        KeyEvent.KEYCODE_SYSTEM_NAVIGATION_LEFT,
        KeyEvent.KEYCODE_SYSTEM_NAVIGATION_RIGHT,
        KeyEvent.KEYCODE_REFRESH,
        KeyEvent.KEYCODE_THUMBS_UP,
        KeyEvent.KEYCODE_THUMBS_DOWN,
        KeyEvent.KEYCODE_PROFILE_SWITCH,
        KeyEvent.KEYCODE_VIDEO_APP_1,
        KeyEvent.KEYCODE_VIDEO_APP_2,
        KeyEvent.KEYCODE_VIDEO_APP_3,
        KeyEvent.KEYCODE_VIDEO_APP_4,
        KeyEvent.KEYCODE_VIDEO_APP_5,
        KeyEvent.KEYCODE_VIDEO_APP_6,
        KeyEvent.KEYCODE_VIDEO_APP_7,
        KeyEvent.KEYCODE_VIDEO_APP_8,
        KeyEvent.KEYCODE_FEATURED_APP_1,
        KeyEvent.KEYCODE_FEATURED_APP_2,
        KeyEvent.KEYCODE_FEATURED_APP_3,
        KeyEvent.KEYCODE_FEATURED_APP_4,
        KeyEvent.KEYCODE_DEMO_APP_1,
        KeyEvent.KEYCODE_DEMO_APP_2,
        KeyEvent.KEYCODE_DEMO_APP_3,
        KeyEvent.KEYCODE_DEMO_APP_4,
        KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_DOWN,
        KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_UP,
        KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_TOGGLE,
        KeyEvent.KEYCODE_STYLUS_BUTTON_PRIMARY,
        KeyEvent.KEYCODE_STYLUS_BUTTON_SECONDARY,
        KeyEvent.KEYCODE_STYLUS_BUTTON_TERTIARY,
        KeyEvent.KEYCODE_STYLUS_BUTTON_TAIL,
        KeyEvent.KEYCODE_RECENT_APPS,
        KeyEvent.KEYCODE_MACRO_1,
        KeyEvent.KEYCODE_MACRO_2,
        KeyEvent.KEYCODE_MACRO_3,
        KeyEvent.KEYCODE_MACRO_4,
        KeyEvent.KEYCODE_EMOJI_PICKER,
        KeyEvent.KEYCODE_SCREENSHOT,
    ).distinct().toIntArray()

    val MODIFIER_KEYCODES: Set<Int>
        get() = setOf(
            KeyEvent.KEYCODE_SHIFT_LEFT,
            KeyEvent.KEYCODE_SHIFT_RIGHT,
            KeyEvent.KEYCODE_ALT_LEFT,
            KeyEvent.KEYCODE_ALT_RIGHT,
            KeyEvent.KEYCODE_CTRL_LEFT,
            KeyEvent.KEYCODE_CTRL_RIGHT,
            KeyEvent.KEYCODE_META_LEFT,
            KeyEvent.KEYCODE_META_RIGHT,
            KeyEvent.KEYCODE_SYM,
            KeyEvent.KEYCODE_NUM,
            KeyEvent.KEYCODE_FUNCTION,
        )

    fun isModifierKey(keyCode: Int): Boolean = keyCode in MODIFIER_KEYCODES

    fun isGamepadKeyCode(keyCode: Int): Boolean {
        when (keyCode) {
            KeyEvent.KEYCODE_BUTTON_A,
            KeyEvent.KEYCODE_BUTTON_B,
            KeyEvent.KEYCODE_BUTTON_C,
            KeyEvent.KEYCODE_BUTTON_X,
            KeyEvent.KEYCODE_BUTTON_Y,
            KeyEvent.KEYCODE_BUTTON_Z,
            KeyEvent.KEYCODE_BUTTON_L1,
            KeyEvent.KEYCODE_BUTTON_R1,
            KeyEvent.KEYCODE_BUTTON_L2,
            KeyEvent.KEYCODE_BUTTON_R2,
            KeyEvent.KEYCODE_BUTTON_THUMBL,
            KeyEvent.KEYCODE_BUTTON_THUMBR,
            KeyEvent.KEYCODE_BUTTON_START,
            KeyEvent.KEYCODE_BUTTON_SELECT,
            KeyEvent.KEYCODE_BUTTON_MODE,
            KeyEvent.KEYCODE_BUTTON_1,
            KeyEvent.KEYCODE_BUTTON_2,
            KeyEvent.KEYCODE_BUTTON_3,
            KeyEvent.KEYCODE_BUTTON_4,
            KeyEvent.KEYCODE_BUTTON_5,
            KeyEvent.KEYCODE_BUTTON_6,
            KeyEvent.KEYCODE_BUTTON_7,
            KeyEvent.KEYCODE_BUTTON_8,
            KeyEvent.KEYCODE_BUTTON_9,
            KeyEvent.KEYCODE_BUTTON_10,
            KeyEvent.KEYCODE_BUTTON_11,
            KeyEvent.KEYCODE_BUTTON_12,
            KeyEvent.KEYCODE_BUTTON_13,
            KeyEvent.KEYCODE_BUTTON_14,
            KeyEvent.KEYCODE_BUTTON_15,
            KeyEvent.KEYCODE_BUTTON_16,
                -> return true

            else -> return false
        }
    }

    /**
     * Get all the valid key codes which work on the Android version for the device.
     */
    fun getKeyCodes(): IntArray {
        return KEYCODES
    }

    fun modifierKeycodeToMetaState(modifier: Int) = when (modifier) {
        KeyEvent.KEYCODE_ALT_LEFT -> KeyEvent.META_ALT_LEFT_ON.withFlag(KeyEvent.META_ALT_ON)
        KeyEvent.KEYCODE_ALT_RIGHT -> KeyEvent.META_ALT_RIGHT_ON.withFlag(KeyEvent.META_ALT_ON)

        KeyEvent.KEYCODE_SHIFT_LEFT -> KeyEvent.META_SHIFT_LEFT_ON.withFlag(KeyEvent.META_SHIFT_ON)
        KeyEvent.KEYCODE_SHIFT_RIGHT -> KeyEvent.META_SHIFT_RIGHT_ON.withFlag(
            KeyEvent.META_SHIFT_ON,
        )

        KeyEvent.KEYCODE_SYM -> KeyEvent.META_SYM_ON

        KeyEvent.KEYCODE_FUNCTION -> KeyEvent.META_FUNCTION_ON

        KeyEvent.KEYCODE_CTRL_LEFT -> KeyEvent.META_CTRL_LEFT_ON.withFlag(KeyEvent.META_CTRL_ON)
        KeyEvent.KEYCODE_CTRL_RIGHT -> KeyEvent.META_CTRL_RIGHT_ON.withFlag(KeyEvent.META_CTRL_ON)

        KeyEvent.KEYCODE_META_LEFT -> KeyEvent.META_META_LEFT_ON.withFlag(KeyEvent.META_META_ON)
        KeyEvent.KEYCODE_META_RIGHT -> KeyEvent.META_META_RIGHT_ON.withFlag(KeyEvent.META_META_ON)

        KeyEvent.KEYCODE_CAPS_LOCK -> KeyEvent.META_CAPS_LOCK_ON
        KeyEvent.KEYCODE_NUM_LOCK -> KeyEvent.META_NUM_LOCK_ON
        KeyEvent.KEYCODE_SCROLL_LOCK -> KeyEvent.META_SCROLL_LOCK_ON

        else -> throw Exception("can't convert modifier $modifier to meta state")
    }

    fun isDpadKeyCode(code: Int): Boolean {
        return code == KeyEvent.KEYCODE_DPAD_LEFT ||
            code == KeyEvent.KEYCODE_DPAD_RIGHT ||
            code == KeyEvent.KEYCODE_DPAD_UP ||
            code == KeyEvent.KEYCODE_DPAD_DOWN ||
            code == KeyEvent.KEYCODE_DPAD_UP_LEFT ||
            code == KeyEvent.KEYCODE_DPAD_UP_RIGHT ||
            code == KeyEvent.KEYCODE_DPAD_DOWN_LEFT ||
            code == KeyEvent.KEYCODE_DPAD_DOWN_RIGHT ||
            code == KeyEvent.KEYCODE_DPAD_CENTER
    }

    fun isGamepadButton(keyCode: Int): Boolean {
        return when (keyCode) {
            KeyEvent.KEYCODE_BUTTON_A,
            KeyEvent.KEYCODE_BUTTON_B,
            KeyEvent.KEYCODE_BUTTON_C,
            KeyEvent.KEYCODE_BUTTON_X,
            KeyEvent.KEYCODE_BUTTON_Y,
            KeyEvent.KEYCODE_BUTTON_Z,
            KeyEvent.KEYCODE_BUTTON_L1,
            KeyEvent.KEYCODE_BUTTON_R1,
            KeyEvent.KEYCODE_BUTTON_L2,
            KeyEvent.KEYCODE_BUTTON_R2,
            KeyEvent.KEYCODE_BUTTON_THUMBL,
            KeyEvent.KEYCODE_BUTTON_THUMBR,
            KeyEvent.KEYCODE_BUTTON_START,
            KeyEvent.KEYCODE_BUTTON_SELECT,
            KeyEvent.KEYCODE_BUTTON_MODE,
            KeyEvent.KEYCODE_BUTTON_1,
            KeyEvent.KEYCODE_BUTTON_2,
            KeyEvent.KEYCODE_BUTTON_3,
            KeyEvent.KEYCODE_BUTTON_4,
            KeyEvent.KEYCODE_BUTTON_5,
            KeyEvent.KEYCODE_BUTTON_6,
            KeyEvent.KEYCODE_BUTTON_7,
            KeyEvent.KEYCODE_BUTTON_8,
            KeyEvent.KEYCODE_BUTTON_9,
            KeyEvent.KEYCODE_BUTTON_10,
            KeyEvent.KEYCODE_BUTTON_11,
            KeyEvent.KEYCODE_BUTTON_12,
            KeyEvent.KEYCODE_BUTTON_13,
            KeyEvent.KEYCODE_BUTTON_14,
            KeyEvent.KEYCODE_BUTTON_15,
            KeyEvent.KEYCODE_BUTTON_16,
                -> true

            else -> false
        }
    }

    fun isKeyCodeUnknown(keyCode: Int): Boolean {
        // The lowest key code is 1 (KEYCODE_SOFT_LEFT)
        return keyCode > KeyEvent.getMaxKeyCode() || keyCode < 1
    }

    fun isPowerButtonKey(keyCode: Int, scanCode: Int): Boolean {
        return keyCode == KeyEvent.KEYCODE_POWER ||
            keyCode == KeyEvent.KEYCODE_TV_POWER ||
            scanCode == Scancode.KEY_POWER ||
            scanCode == Scancode.KEY_POWER2
    }
}
